Introduction
This template helps developers (or an AI coding assistant like Cursor/Claude) to audit and optimise any SQL query executed inside the Farfalla code-base.
Copy the prompt, fill in the placeholders, and paste it into Cursor. The assistant will gather execution plans, index information, and produce a ✅ / ❌ style report.
Prompt Template
You are analysing the performance of the following Eloquent/Laravel query (or raw SQL):
<QUERY_OR_CODE_BLOCK_HERE>
1. Show the current _indexes_ on every table touched by the query.
– Use `SHOW INDEXES FROM <table>`.
2. Show the full table definition to identify **ROWSTORE/COLUMNSTORE**, **SHARD KEY**, and **SORT KEY**.
– Use `SHOW CREATE TABLE <table>`.
3. Execute the query with `DB::enableQueryLog()` (or run it directly) and list all **generated SQL statements**.
4. For **each** SQL statement, run `EXPLAIN ANALYZE` (SingleStore) and collect the execution plan.
5. Produce a report that lists, for every table and every plan:
- ✅ things already well-optimised (good access type, correct index, co-located shards, etc.)
- ❌ issues detected (full scans, repartitioning, missing indexes, bad shard/sort key, etc.)
- ⚠️ items that are acceptable for now but should be improved if time permits (e.g., low-impact full scans, moderate cardinality issues).
- Concrete recommendations: `CREATE INDEX …`, `ALTER TABLE … SHARD KEY`, move to ROWSTORE/COLUMNSTORE, etc.
6. Summarise high-impact improvements in priority order.
7. At the end of the report, include a **step-by-step action list** (bullet points) that can be copied into Cursor’s todo list, one actionable task per line.
Tip: When the assistant asks for clarifications, provide the raw SQL generated by the query and any relevant table schema snippets.
Example Usage
- Identify the Eloquent method you want to analyse, e.g.
OrdersService::getSubscriptionsQuery(). - Replace
<QUERY_OR_CODE_BLOCK_HERE>with the literal PHP code or the raw SQL. - Run the prompt in Cursor. The assistant will automatically execute
SHOW INDEXES,SHOW CREATE TABLE, andEXPLAIN ANALYZEusing the project aliases (zar,zex).
You are analysing the performance of the following query:
OrdersService::getSubscriptionsQuery(null)->cursorPaginate(15);
… (rest of template as above)
Alias note: When running ad-hoc SQL in your terminal, use
zar php artisan tinker --execute="SQL_HERE"(orzexfor non-artisan commands) so the queries run inside the Docker container.
Additional Notes
- Laravel model conventions
- Before running
SHOW INDEXESorSHOW CREATE TABLE, first inspect the Eloquent models (and their relationships such asbelongsTo,hasMany, etc.) to identify the actual table name (protected $table) and avoid failed queries.
- Before running
- SingleStore specifics
- Prefer
EXPLAIN ANALYZEover plainEXPLAINto get execution times. - Remember that
SHARD KEYmis-match causes repartitioning; co-locate joins on the same key. ROWSTOREtables are best for high-churn OLTP;COLUMNSTOREfor analytical scans.- Farfalla runs on SingleStore v8.7 – verify that any recommended syntax is compatible with this version.
- Convention: every table starts with a
tenant_idcolumn; favour composite indexes wheretenant_idis the first field.
- Prefer
- Safety
- Use
LIMITwhen running heavy selects. - If any step returns a 500 (server) error, stop the automated analysis and surface the error so that a human can decide how to proceed.
- Use
Index / Shard / Sort Key patterns (internal examples 2025 a)
Use the following conventions—derived from recent 2025 migrations—when writing the concrete recommendations section of the report:
| Pattern | Example (from migration) | When to use |
|---|---|---|
| Multi-column HASH index | ALTER TABLE prices ADD KEY discount_shelf_index (deleted_at, discount_percentage, priceable_type, priceable_id, ends_at) USING HASH; | Filters with 3+ equality predicates where order of columns is not required for range scans. |
| Composite BTREE index for tenant scoping | ALTER TABLE payments ADD KEY (order_id, tenant_id); | High-cardinality order_id lookups scoped by tenant_id. |
| Shard key + sort key combo | ```php | |
| $table->shardKey('list_id'); | ||
| $table->sortKey(['product_type', 'product_id']); |
Guidelines:
1. **Always include `tenant_id`** in composite keys when queries filter by it.
2. For tables accessed mostly via equality, prefer **`USING HASH`**.
3. Define a **`shardKey()`** first, then a **`sortKey()`** for intra-shard ordering.
4. Keep index names descriptive: `<table>_<purpose>_index`.
5. If rebuilding a large table to add shard/sort keys, follow the *copy-swap* pattern: create new table → copy data → rename.
When your analysis suggests adding an index, reference this table to pick the appropriate pattern.
---
## See Also
- [SingleStore Documentation – Performance Tuning](https://docs.singlestore.com/)
- Internal guide: [database optimisation checklist](mdc:.cursor/rules/performance.mdc)